#ifndef YHAIDA_TCPCONNECTION_H
#define YHAIDA_TCPCONNECTION_H
#include "../base/Utils.h"
#include "../base/WeakCallback.h"
#include "InetAddress.h"
#include "Callbacks.h"
#include "InetAddress.h"
#include "../logging/Logging.h"
#include "SocketsOps.h"
#include "Buffer.h"
#include <memory>
#include <string>
#include <boost/any.hpp>
namespace yhaida
{
    class Channel;
    class EventLoop;
    class Socket;

    /*
    TcpConnection其实和Channel是对应起来的
    */
    class TcpConnection : Utils::nocapyable,
                          public std::enable_shared_from_this<TcpConnection>
    {
    public:
        TcpConnection(EventLoop *loop,
                      const std::string &name,
                      int sockfd,
                      const InetAddress &localAddr,
                      const InetAddress &peerAddr);
        ~TcpConnection();

        EventLoop *getLoop() { return _mainEventLoop; }
        const std::string &name() { return _name; }
        const InetAddress &localhostAddress() { return _localhostAddress; }
        const InetAddress &peerAddress() { return _peerAddress; }
        bool connected() const { return _state == kConnected; }

        //发送与关闭->是用户接口
        void send(const char *str, size_t length);
        void send(const std::string &str);
        void send(Buffer *buff);
        void shutdown();
        void forceCloseWithDelay(double seconds);
        void forceClose();
        void forceCloseInLoop();
        //
        void startRead();
        void startReadInLoop();
        void stopRead();
        void stopReadInLoop();

        void setConnectionCallback(const ConnectionCallback &cb)
        {
            _connectionCallback = cb;
        }
        void setMessageCallback(const MessageCallback &cb)
        {
            _messageCallback = cb;
        }

        void setCloseCallback(const CloseCallback &cb)
        {
            _closeCallback = cb;
        }
        void setWriteCompleteCallback(const WriteCompleteCallback &cb)
        {
            _writeCompleteCallback = cb;
        }
        void setHighWaterMarkCallback(const HighWaterMarkCallback &cb, size_t highWaterMark)
        {
            _highWaterMarkCallback = cb;
            _highWaterMark = highWaterMark;
        }

        //注册connfd的fd与channel
        void connectEstablished();
        //销毁connfd的fd与channel
        void connectDestroyed();

                //禁用Nagle
        void setTcpNoDelay(bool on);
        //保活
        void setTcpKeepAlive(bool on);

        Buffer *inputBuffer()
        {
            return &_inputBuffer;
        }

        Buffer *outputBuffer()
        {
            return &_outputBuffer;
        }

        void setContext(const boost::any &context)
        {
            _context = context;
        }

        const boost::any &getContext() const
        {
            return _context;
        }
        boost::any *getMutableContext()
        {
            return &_context;
        }

        //http
        void setHttpContext(const boost::any &context)
        {
            _httpContext = context;
        }

        const boost::any &getHttpContext() const
        {
            return _httpContext;
        }
        boost::any *getMutableHttpContext()
        {
            return &_httpContext;
        }

        //time
        void setTimeContext(const boost::any &context)
        {
            _timeContext = context;
        }

        const boost::any &getTimeContext() const
        {
            return _timeContext;
        }
        boost::any *getMutableTimeContext()
        {
            return &_timeContext;
        }


    private:
        enum StateE
        {
            kConnecting,
            kConnected,
            kDisconnecting,
            kDisconnected,
        };

        void setState(StateE state) { _state = state; }

        EventLoop *_mainEventLoop;
        std::string _name;

        StateE _state;

        /*
        1.下面这四个函数是fd触发后执行的
        void handleRead(Timestamp receiveTime);
        void handleWrite();
        void handleError();
        void handleClose();
        2.下面这三个函数是accept分配时候注册的
        ConnectionCallback _connectionCallback;
        MessageCallback _messageCallback;
        CloseCallback _closeCallback;

        */
        // Socket(fd) + handleRead() = Channel;
        void handleRead(Timestamp receiveTime);
        void handleWrite();
        void handleError();
        void handleClose();

        void sendInLoop(const std::string &str);
        void sendInLoop(const void *str, size_t length);
        void shutdownInLoop();

        std::unique_ptr<Socket> _sockfd; //一个TCP一个Socket（RAII fd）
        std::unique_ptr<Channel> _channel;

        InetAddress _localhostAddress; //本地地址
        InetAddress _peerAddress;      //对方地址

        ConnectionCallback _connectionCallback;
        MessageCallback _messageCallback;
        CloseCallback _closeCallback;
        WriteCompleteCallback _writeCompleteCallback;
        size_t _highWaterMark;
        HighWaterMarkCallback _highWaterMarkCallback;

        Buffer _inputBuffer;
        Buffer _outputBuffer;

        boost::any _context;
        boost::any _httpContext;
        boost::any _timeContext;
        bool _reading;
    };
    typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;
    
    void defaultConnectionCallback(const TcpConnectionPtr &conn);
    

    void defaultMessageCallback(const TcpConnectionPtr &,
                                Buffer *buffer,
                                Timestamp);

}

#endif